<script setup lang="ts">
import type { FullModelInfo } from '@/services/model/type'
import { onMounted, ref, reactive, watch, computed } from 'vue'
import { CubeLink20Regular, ArrowSync20Regular } from '@vicons/fluent'
import { Icon } from '@vicons/utils'
import { storeToRefs } from 'pinia'
import { useGlobalStore } from '@/stores/global'
import { useModelStore } from '@/stores/model'
import { message } from 'ant-design-vue'
import ModelsAction from './components/ModelsAction.vue'

// 全局存储
const globalStore = useGlobalStore()
// 模型存储
const modelStore = useModelStore()
const { readActiveSuppliers } = storeToRefs(modelStore)

// 外部参数
const props = defineProps({
  // 是否手机模式
  isMobile: {
    type: Boolean,
    required: true,
  },
})

// 状态参数
const state = reactive({
  // 全局错误
  globalError: '',
  // 拉取模型冷却
  pullCd: 0,
  // 连接冷却
  connectCd: 0,
  // 当前激活的 tab
  currentTab: '',
  // 当前名称
  currentName: '',
  // 默认展开
  expandNames: [],
  // 是否拉取中
  isLoadingUsable: false,
})

// 当前标签页展示的模型
const currentPageModels = ref<FullModelInfo[]>([])

// 当前已添加的模型
const currentAddModels = computed(() => {
  return currentPageModels.value.filter(
    (item) => item.supplier.id === state.currentTab && item.inUse,
  )
})

// 当前待添加的模型
const currentUsableModels = computed(() => {
  return currentPageModels.value.filter(
    (item) => item.supplier.id === state.currentTab && !item.inUse,
  )
})

// 表单数据
const formData = reactive({
  baseUrl: '',
  apiKey: '',
})

// 检测连接正确
const onCheck = async () => {
  if (state.connectCd > 0) {
    return
  }
  state.connectCd = 1
  const loading = message.loading(`正在访问 ${state.currentName} API...`, 0)
  try {
    if (await modelStore.checkSupplier(state.currentTab)) {
      loading()
      message.success(`${state.currentName} API 访问成功`)
    } else {
      loading()
      message.error(`${state.currentName} API 访问超时：请确认配置信息`)
    }
  } catch (error) {
    loading()
    message.error(`${state.currentName} API 访问失败：` + error)
  }
  setTimeout(() => {
    state.connectCd = 0
  }, 1000)
}

// 拉取模型
const handlePullModel = async () => {
  if (state.pullCd > 0) {
    return
  }
  state.pullCd = 1
  const loading = message.loading(`正在访问 ${state.currentName} API...`, 0)
  try {
    await loadCurrentModels(true)
    loading()
    message.success(`${state.currentName} 模型已更新`)
  } catch (error) {
    loading()
    message.error(`${state.currentName} 模型获取失败：` + error)
    currentPageModels.value = []
  }
  setTimeout(() => {
    state.pullCd = 0
  }, 1000)
}

// 模型添加
const onAddModel = async (model: FullModelInfo) => {
  await modelStore.setModelInUse(model.id, true)
  await loadCurrentModels()
}

// 模型移除
const onDelModel = async (model: FullModelInfo) => {
  await modelStore.setModelInUse(model.id, false)
  await loadCurrentModels()
}

// 加载当前标签模型
const loadCurrentModels = async (forceRefresh: boolean = false) => {
  currentPageModels.value = await modelStore.getSupplierModels(state.currentTab, forceRefresh)
}

onMounted(() => {
  // 页面初始化（大标签切换也触发）
  if (readActiveSuppliers.value.length) {
    const firstTab = readActiveSuppliers.value[0].id
    state.currentTab = globalStore.getStagingValue('ss-tab', firstTab)
  } else {
    state.globalError = '暂未激活供应商信息，无法读取模型。请前往 /src/config/index.ts 进行设置'
  }
})

// 监听：切换标签
watch(
  () => state.currentTab,
  async (value) => {
    state.expandNames = ['added', 'usable']
    if (value) {
      state.isLoadingUsable = true
      globalStore.setStagingValue('ss-tab', value)
      const supplier = readActiveSuppliers.value.find((item) => item.id === value)
      if (supplier) {
        // 设置显示数据
        state.currentName = supplier.name
        formData.baseUrl = supplier.baseUrl
        formData.apiKey = supplier.apiKey
        // 加载模型
        loadCurrentModels()
          .catch((error) => {
            window.console.error(error)
            message.error(`加载 ${state.currentName} 模型失败：` + error)
            currentPageModels.value = []
          })
          .finally(() => {
            state.isLoadingUsable = false
          })
      } else {
        state.globalError = '404'
      }
    }
  },
  { immediate: true },
)
</script>

<template>
  <div>
    <n-alert v-if="state.globalError" title="错误" type="error">
      {{ state.globalError }}
    </n-alert>
    <template v-else>
      <n-tabs
        v-if="readActiveSuppliers.length > 1"
        class="tabs"
        v-model:value="state.currentTab"
        type="card"
        :animated="true"
      >
        <n-tab-pane
          v-for="(item, index) of readActiveSuppliers"
          :key="index"
          :name="item.id"
          :tab="item.name"
        >
        </n-tab-pane>
      </n-tabs>
      <n-form ref="formRef" class="form" :class="{ mobile: props.isMobile }" :model="formData">
        <n-form-item path="baseUrl" :label="state.currentName + ' API 地址'">
          <n-input v-model:value="formData.baseUrl" placeholder="请输入" readonly />
        </n-form-item>
        <n-form-item path="apiKey" :label="state.currentName + ' API 密钥'">
          <n-input-group>
            <n-input
              type="password"
              v-model:value="formData.apiKey"
              placeholder="暂无"
              show-password-on="click"
              readonly
            />
            <n-button type="default" :disabled="state.connectCd > 0" @click="onCheck">
              <template #icon>
                <Icon><CubeLink20Regular /></Icon>
              </template>
              验证
            </n-button>
          </n-input-group>
        </n-form-item>
      </n-form>
      <n-collapse class="model" v-model:expanded-names="state.expandNames">
        <n-collapse-item title="已添加模型" name="added">
          <template #header-extra>
            <n-tag v-if="currentAddModels.length" :bordered="false" type="success">
              {{ currentAddModels.length }}
            </n-tag>
          </template>
          <ModelsAction
            type="del"
            :models="currentAddModels"
            empty-text="尚未添加模型"
            @action="onDelModel"
          />
        </n-collapse-item>
        <n-collapse-item :title="state.currentName + ' 可添加模型'" name="usable">
          <template #header-extra>
            <a-tooltip trigger="hover" placement="top">
              <n-button
                type="primary"
                size="small"
                secondary
                :disabled="state.pullCd > 0"
                @click.stop="handlePullModel"
              >
                <template #icon>
                  <Icon><ArrowSync20Regular /></Icon>
                </template>
                <span>获取模型</span>
              </n-button>
              <template #title>
                从 {{ state.currentName }} 服务器获取模型列表，需要在服务器中安装模型。
              </template>
            </a-tooltip>
          </template>
          <a-skeleton v-if="state.isLoadingUsable" active />
          <template v-else>
            <ModelsAction
              type="add"
              :models="currentUsableModels"
              empty-text="暂无可添加模型"
              @action="onAddModel"
            />
          </template>
        </n-collapse-item>
      </n-collapse>
    </template>
  </div>
</template>

<style lang="scss" scoped>
.tabs {
  padding-bottom: 20px;
  &.mobile {
    padding-bottom: 12px;
  }
}
</style>
